home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1998 / MacHack 1998.toast / Papers / C++ Exceptions / µShell / Core Utilities / Exceptions.cp < prev    next >
Encoding:
Text File  |  1998-04-01  |  18.0 KB  |  885 lines  |  [TEXT/CWIE]

  1. #define __NO_LOCATION_MACROS__
  2. #ifndef __EXCEPTIONS__
  3. #include "Exceptions.h"
  4. #endif
  5. #ifndef __DEBUGWRITE__
  6. #include "DebugWrite.h"
  7. #endif
  8. #ifndef __AEEXTRAS__
  9. #include "AEExtras.h"
  10. #endif
  11. #ifndef __STRINGUTILS__
  12. #include "StringUtils.h"
  13. #endif
  14.  
  15. #ifndef __OSA__
  16. #include <OSA.h>
  17. #endif
  18. #ifndef __TEXTUTILS__
  19. #include <TextUtils.h>
  20. #endif
  21. #ifndef __KEYUTILS__
  22. #include "KeyUtils.h"
  23. #endif
  24.  
  25. #include <string.h>
  26.  
  27. //------------------------------------------------------------------------------
  28.  
  29. #if qDebug
  30. bool                                Exception::gBreakOnThrow    = false;
  31. bool                                Exception::gLogExceptions    = false;
  32. #endif
  33.  
  34. Exception::ReportExceptionProcPtr    Exception::gReportProc        = nil;
  35.  
  36. //------------------------------------------------------------------------------
  37.  
  38. void LocationInCode::AppendToString(Str255& str) const
  39. {
  40.     Str15    line;
  41.     
  42.     NumToString(fLineNum, line);
  43.  
  44.     cpstrcat(str, fFileName);
  45.     pstrcat(str, "\p, line ");
  46.     pstrcat(str, line);
  47.  
  48. #if 0
  49.     unsigned char    tmpBuf[kErrorBufferSize];
  50.     unsigned char     length;
  51.     
  52.     // since this is debug only, hard coded strings are acceptable.
  53.     memset(fErrorString,0,kErrorBufferSize); 
  54.     
  55.     // make a nice error message from the info we get…
  56.     strcpy((char *)fErrorString,"•Assertion Failed• Source File: ");    
  57.     if(fileName)
  58.         strcat((char *)fErrorString,fileName);
  59.     strcat((char *)fErrorString," | Line Number: ");
  60.     NumToString(lineNum,tmpBuf);
  61.     BlockMove(tmpBuf+1,fErrorString+strlen((char *)fErrorString),tmpBuf[0]);
  62.     strcat((char *)fErrorString,"•");
  63.     
  64.     // REVIEW: This might be a nice place to add Macsbug data - AD
  65.     
  66.     // perform a dirty C to P string conversion…
  67.     length = strlen((char *)fErrorString);
  68.     if(length){
  69.         BlockMove(fErrorString,fErrorString+1,length);
  70.     }
  71.     fErrorString[0] = length;
  72. #endif
  73. }
  74.  
  75. //------------------------------------------------------------------------------
  76.  
  77. bool Exception::IsFatal(void) const
  78. {
  79.     return false;
  80. }
  81.  
  82. //------------------------------------------------------------------------------
  83.  
  84. bool Exception::IsSilent(void) const
  85. {
  86.     return false;
  87. }
  88.  
  89. //------------------------------------------------------------------------------
  90.  
  91. void Exception::AboutToThrow(void) const
  92. {
  93.     if (qDebug)
  94.     {
  95.         if (BreakOnThrow() || KeyIsDown(kCapsLockKeyCode))
  96.         {
  97.             Str255    msg;
  98.  
  99.             SysBreakFunc("\pError thrown: ");
  100.             GetErrorString(msg);
  101.             SysBreakFunc(msg);
  102.             Debugger();
  103.         }
  104.         else if (LogExceptions())
  105.         {
  106.             DebugWrite("\pthrowing ");
  107.             Log();
  108.         }
  109.     }
  110. }
  111.  
  112. //------------------------------------------------------------------------------
  113.  
  114. OSErr Exception::GetOSErr(void) const
  115. {
  116.     OSStatus status = GetStatus();
  117.  
  118.     if (status <= SHRT_MAX && status >= SHRT_MIN)
  119.     {
  120.         return (OSErr) status;
  121.     }
  122.     else
  123.     {
  124.         return eGeneralErr;
  125.     }
  126. }
  127.  
  128. //------------------------------------------------------------------------------
  129.  
  130. OSStatus Exception::GetStatus(void) const
  131. {
  132.     return fStatus;
  133. }
  134.  
  135. //------------------------------------------------------------------------------
  136.  
  137. OSStatus Exception::SetStatus(OSStatus status)
  138. {
  139.     OSStatus oldStatus = fStatus;
  140.  
  141.     fStatus = status;
  142.  
  143.     return oldStatus;
  144. }
  145.  
  146. //------------------------------------------------------------------------------
  147.  
  148. /*
  149. long Exception::GetMessage(void) const
  150. {
  151.     return 0;
  152. }
  153.  
  154. //------------------------------------------------------------------------------
  155.  
  156. long Exception::SetMessage(long message)
  157. {
  158.     return 0;
  159. }
  160. */
  161.  
  162. //------------------------------------------------------------------------------
  163.  
  164. bool Exception::GetErrorMessage(AEDesc& msg) const
  165. {
  166.     Str255    str;
  167.     
  168.     bool result = this->GetErrorString(str);
  169.  
  170.     if (result)
  171.     {
  172.         GetLocationInCode().LogIfErr(AECreateDesc(typeChar, &str[1], str[0], &msg));
  173.     }
  174.     
  175.     return result;
  176. }
  177.  
  178. //------------------------------------------------------------------------------
  179.  
  180. bool Exception::GetErrorString(Str255& msg) const
  181. {
  182.     NumToString(this->GetStatus(), msg);
  183.         
  184.     pstrcat(msg, "\p (");
  185.     fThrowPoint.AppendToString(msg);
  186.     pstrcat(msg, "\p)");
  187.  
  188.     return true;
  189. }
  190.  
  191. //------------------------------------------------------------------------------
  192.  
  193. void Exception::Log() const
  194. {
  195.     Str255 message; message[0] = '\0';
  196.  
  197.     fThrowPoint.AppendToString(message);
  198.  
  199.     DebugWrite("\perror ");
  200.     DebugWriteNum(fStatus);
  201.     DebugWrite("\p ");
  202.     DebugWriteLn(message);
  203.  
  204.     fThrowPoint.LogIfErr(GetStatus());
  205. }
  206.  
  207. //------------------------------------------------------------------------------
  208.  
  209. void Exception::Report() const
  210. {
  211.     if (gReportProc != nil)
  212.     {
  213.         (*gReportProc)(*this);
  214.     }
  215. }
  216.  
  217. //------------------------------------------------------------------------------
  218.  
  219. OSErr Exception::GetAEParams(AERecord& result, bool create) const
  220. {
  221.     OSErr err = noErr;
  222.  
  223.     // create a new record if we were passed null
  224.  
  225.     if (result.descriptorType == typeNull)
  226.     {
  227.         if (create)
  228.         {
  229.             err = AECreateList(nil, 0, true, &result);
  230.         }
  231.         else
  232.         {
  233.             return noErr;
  234.         }
  235.     }
  236.  
  237.     // fill in keyErrorNumber and keyErrorString if not already present
  238.  
  239.     if (err == noErr)
  240.     {
  241.         DescType    typeCode;
  242.         Size        actualSize;
  243.         long        oldErr;
  244.  
  245.         if (AEGetParamPtr(&result, keyErrorNumber, typeLongInteger, &typeCode,
  246.                               &oldErr, sizeof(oldErr), &actualSize) != noErr
  247.         ||    oldErr != noErr)
  248.         {
  249.             PutErrorNumber(result);
  250.         }
  251.  
  252.         if (AESizeOfParam(&result, keyErrorString, &typeCode, &actualSize)
  253.         !=    noErr)
  254.         {
  255.             PutErrorString(result);
  256.         }
  257.     }
  258.  
  259.     return err;    
  260. }
  261.  
  262. //------------------------------------------------------------------------------
  263.  
  264. bool Exception::PutErrorNumber(AERecord& event) const
  265. {
  266.     OSStatus err = GetStatus();
  267.     
  268.     GetLocationInCode().LogIfErr(AEPutParamPtr(&event, keyErrorNumber, typeLongInteger, &err,
  269.                                sizeof(err)));
  270.  
  271.     return true;
  272. }
  273.  
  274. //------------------------------------------------------------------------------
  275.  
  276. bool Exception::PutErrorString(AERecord& event) const
  277. {
  278.     AEDesc    desc;
  279.  
  280.     bool result = GetErrorMessage(desc);
  281.  
  282.     if (result)
  283.     {
  284.         GetLocationInCode().LogIfErr(::AEPutParamDesc(&event, keyErrorString, &desc));
  285.         GetLocationInCode().LogIfErr(::AEDisposeDesc(&desc));
  286.     }
  287.  
  288.     return result;    
  289. }
  290.  
  291. //------------------------------------------------------------------------------
  292.  
  293. bool Exception::HasExpectedType() const
  294. {
  295.     return HasErrorParam(kOSAErrorExpectedType);
  296. }
  297.  
  298. //------------------------------------------------------------------------------
  299.  
  300. void Exception::PutExpectedType(
  301.     DescType    expectedType,
  302.     DescType    actualType,
  303.     bool        overwrite)
  304. {
  305.     if (expectedType)
  306.     {
  307.         PutErrorParamPtr(kOSAErrorExpectedType,
  308.                          typeType,
  309.                          &expectedType,
  310.                          sizeof(expectedType),
  311.                          overwrite);
  312.     }
  313.         
  314.     if (actualType)
  315.     {
  316.         PutErrorParamPtr(keyAEErrorActualType,
  317.                          typeType,
  318.                          &expectedType,
  319.                          sizeof(expectedType),
  320.                          overwrite);
  321.     }                                      
  322. }
  323.  
  324. //------------------------------------------------------------------------------
  325.  
  326. bool Exception::HasOffendingObject() const
  327. {
  328.     return HasErrorParam(kOSAErrorOffendingObject);
  329. }
  330.  
  331. //------------------------------------------------------------------------------
  332.  
  333. void Exception::PutOffendingObject(const AEDesc& objectSpec, bool    overwrite)
  334. {
  335.     PutErrorParamDesc(kOSAErrorOffendingObject, objectSpec, overwrite);
  336. }
  337.  
  338. //------------------------------------------------------------------------------
  339.  
  340. bool Exception::HasOffendingParameter() const
  341. {
  342.     return HasErrorParam(kOSAErrorOffendingObject);
  343. }
  344.  
  345. //------------------------------------------------------------------------------
  346.  
  347. void Exception::PutOffendingParameter(AEKeyword param, bool    overwrite)
  348. {
  349.     PutErrorParamPtr(kOSAErrorOffendingObject,
  350.                      typeKeyword,
  351.                      ¶m,
  352.                      sizeof(param),
  353.                      overwrite);
  354. }
  355.  
  356. //------------------------------------------------------------------------------
  357.  
  358. bool Exception::HasErrorParam(AEKeyword    /*param*/) const
  359. {
  360.     return false;
  361. }
  362.  
  363. //------------------------------------------------------------------------------
  364.  
  365. void Exception::PutErrorParamPtr(
  366.     AEKeyword    /*param*/,
  367.     DescType    /*type*/,
  368.     const void*    /*data*/,
  369.     Size        /*size*/,
  370.     bool        /*overwrite*/)
  371. {
  372.     // Drop on the floor by default
  373. }
  374.  
  375.  
  376. //------------------------------------------------------------------------------
  377.  
  378. void Exception::PutErrorParamDesc(
  379.     AEKeyword        /*param*/,
  380.     const AEDesc&    /*desc*/,
  381.     bool            /*overwrite*/)
  382. {
  383.     // Drop on the floor by default
  384. }
  385.  
  386. //------------------------------------------------------------------------------
  387.  
  388. OSStatus Exception::vStandardizeExceptions(VAProc proc, va_list arg)
  389. {
  390.     StdException exc(GetLocationInCode()); // premptive exception
  391.  
  392.     try                                // Call the proc
  393.     {
  394.         return (*proc)(arg);
  395.     }
  396.     catch (Exception& err)            // Exceptions are OK
  397.     {
  398.         throw /*err*/;
  399.     }
  400.     catch (char* msg)
  401.     {
  402.         exc.PutErrorParamPtr(keyErrorString, typeChar, msg, strlen(msg));
  403.     }
  404.     catch (long num)
  405.     {
  406.         exc.SetStatus(num);
  407.     }
  408.     catch (...)
  409.     {
  410.     }
  411.  
  412.     if (LogExceptions())
  413.     {
  414.         exc.Log();
  415.     }
  416.  
  417.     exc.AboutToThrow();
  418.  
  419.     throw exc;
  420.  
  421.     return 0;
  422. }
  423.  
  424. //------------------------------------------------------------------------------
  425.  
  426. Exception::ReportExceptionProcPtr Exception::SetReportProc(ReportExceptionProcPtr newProc)
  427. {
  428.     ReportExceptionProcPtr oldProc = gReportProc;
  429.     
  430.     gReportProc = newProc;
  431.     
  432.     return oldProc;
  433. }    
  434.  
  435. #if    qDebug
  436. //------------------------------------------------------------------------------
  437.  
  438. bool Exception::SetLogExceptions(bool newState)
  439. {
  440.     bool oldState = gLogExceptions;
  441.     
  442.     gLogExceptions = newState;
  443.     
  444.     return oldState;
  445. }
  446.  
  447. //------------------------------------------------------------------------------
  448.  
  449. bool Exception::SetBreakOnThrow(bool newState)
  450. {
  451.     bool oldState = gBreakOnThrow;
  452.     
  453.     gBreakOnThrow = newState;
  454.     
  455.     return oldState;
  456. }
  457. #endif
  458.  
  459. //------------------------------------------------------------------------------
  460.  
  461. OSStatus Exception::StandardizeExceptions(VAProc proc, ...)
  462. {
  463.     va_list arg; va_start(arg, proc);
  464.  
  465.     return vStandardizeExceptions(proc, arg);
  466. }
  467.  
  468. //------------------------------------------------------------------------------
  469.  
  470.     static OSStatus report_exception(va_list arg)
  471.     {
  472.         VA_ARG(Exception*, exc, arg);
  473.     
  474.         exc->Report();
  475.  
  476.         return 0;
  477.     }
  478.  
  479. void Exception::ReportExceptions(VAProc proc, ...)
  480. {
  481.     va_list arg; va_start(arg, proc);
  482.  
  483.     try
  484.     {
  485.         GetLocationInCode().FailOSStatus(vStandardizeExceptions(proc, arg));
  486.  
  487.         va_end(arg);
  488.     }
  489.     catch (Exception& exc)
  490.     {
  491.         va_end(arg);
  492.  
  493.         StandardizeExceptions(report_exception, &exc);
  494.  
  495.         throw;
  496.     }
  497. }
  498.  
  499. //------------------------------------------------------------------------------
  500.  
  501. OSErr Exception::CatchAEErrors(AppleEvent* event, VAProc proc, ...)
  502. {
  503.     va_list arg; va_start(arg, proc);
  504.  
  505.     OSStatus status; 
  506.  
  507.     try
  508.     {
  509.         status = vStandardizeExceptions(proc, arg);
  510.     }
  511.     catch (Exception& exc)
  512.     {
  513.         status = exc.GetOSErr();
  514.  
  515.         if (event && event->dataHandle != nil)
  516.         {
  517.             if (status != errAEEventNotHandled)
  518.             {
  519.                 // AppleScript has an undocumented "feature" where if we put
  520.                 // an error parameter in an unhandled event, it reports an
  521.                 // error rather than trying the system handlers.
  522.             
  523.                 GetLocationInCode().LogIfErr(exc.GetAEParams(*event, false));
  524.             }
  525.         }
  526.     }
  527.  
  528.     va_end(arg);
  529.  
  530.     if (status <= SHRT_MAX && status >= SHRT_MIN)
  531.     {
  532.         return (OSErr) status;
  533.     }
  534.     else
  535.     {
  536.         return eGeneralErr;
  537.     }
  538. }
  539.  
  540. //------------------------------------------------------------------------------
  541.  
  542. OSStatus Exception::CatchOSStatus(VAProc proc, ...)
  543. {
  544.     va_list arg; va_start(arg, proc);
  545.  
  546.     OSStatus status; 
  547.  
  548.     try
  549.     {
  550.         status = vStandardizeExceptions(proc, arg);
  551.     }
  552.     catch (Exception& exc)
  553.     {
  554.         status = exc.GetStatus();
  555.     }
  556.  
  557.     va_end(arg);
  558.  
  559.     return status;
  560. }
  561.  
  562. //------------------------------------------------------------------------------
  563.  
  564. OSErr Exception::CatchOSErrors(VAProc proc, ...)
  565. {
  566.     va_list arg; va_start(arg, proc);
  567.  
  568.     OSStatus status; 
  569.  
  570.     try
  571.     {
  572.         status = vStandardizeExceptions((VAProc) proc, arg);
  573.         va_end(arg);
  574.         return noErr;
  575.     }
  576.     catch (Exception& exc)
  577.     {
  578.         status = exc.GetOSErr();
  579.     }
  580.  
  581.     va_end(arg);
  582.  
  583.     if (status <= SHRT_MAX && status >= SHRT_MIN)
  584.     {
  585.         return (OSErr) status;
  586.     }
  587.     else
  588.     {
  589.         return eGeneralErr;
  590.     }
  591. }
  592.  
  593. //------------------------------------------------------------------------------
  594.  
  595. void Exception::MakeTextDesc(AEDesc& desc, const char *cstr)
  596. {
  597.     desc.descriptorType    = typeNull;
  598.     desc.dataHandle        = nil;
  599.  
  600.     if (cstr)
  601.     {
  602.         GetLocationInCode().LogIfErr(AECreateDesc(typeChar, cstr, strlen(cstr), &desc));
  603.     }
  604. }
  605.  
  606. //------------------------------------------------------------------------------
  607.  
  608. void Exception::MakeTextDesc(AEDesc& desc, ConstStr255Param pstr)
  609. {
  610.     desc.descriptorType    = typeNull;
  611.     desc.dataHandle        = nil;
  612.  
  613.     if (pstr)
  614.     {
  615.         GetLocationInCode().LogIfErr(AECreateDesc(typeChar, &pstr[1], pstr[0], &desc));
  616.     }
  617. }
  618.  
  619. //==============================================================================
  620.  
  621. SilentException::~SilentException()
  622. {
  623. }
  624.  
  625. //------------------------------------------------------------------------------
  626.  
  627. void SilentException::Log() const
  628. {
  629. }
  630.  
  631. //------------------------------------------------------------------------------
  632.  
  633. void SilentException::Report() const
  634. {
  635. }
  636.  
  637. //------------------------------------------------------------------------------
  638.  
  639. bool SilentException::IsSilent(void) const
  640. {
  641.     return true;
  642. }
  643.  
  644. //------------------------------------------------------------------------------
  645.  
  646. OSErr SilentException::GetAEParams(AERecord& /*evt*/, bool /*create*/) const
  647. {
  648.     return noErr;
  649. }
  650.  
  651. //==============================================================================
  652.  
  653. StdException::StdException(const StdException& exc)
  654. :    Exception(exc)
  655. {
  656.     GetLocationInCode().LogIfErr(AEDuplicateDesc(&exc.fErrParams, &fErrParams));
  657. }
  658.  
  659. //------------------------------------------------------------------------------
  660.  
  661. /*
  662. StdException::StdException(
  663.     const LocationInCode&    where,
  664.     OSStatus                status,
  665.     AEDesc*                    params)
  666. :    Exception(where, status)
  667. {
  668.     if (params)
  669.     {
  670.         fErrParams = *params;
  671.     }
  672.     else
  673.     {
  674.         params = &fErrParams;
  675.     }
  676.  
  677.     params->descriptorType    = typeNull;
  678.     params->dataHandle        = nil;
  679. }
  680. */
  681.  
  682. //------------------------------------------------------------------------------
  683.  
  684. StdException::~StdException()
  685. {
  686.     GetLocationInCode().LogIfErr(AEDisposeDesc(&fErrParams));
  687. }
  688.  
  689. //------------------------------------------------------------------------------
  690.  
  691. void StdException::Log() const
  692. {
  693.     Exception::Log();
  694.  
  695.     if (fErrParams.descriptorType != typeNull)
  696.     {
  697.         DebugWriteAE(&fErrParams);
  698.         DebugWriteLn("\p", false);
  699.     }
  700. }
  701.  
  702. //------------------------------------------------------------------------------
  703.  
  704. OSErr StdException::GetAEParams(AERecord& evt, bool create) const
  705. {
  706.     OSErr err = noErr;
  707.     
  708.     if (create || evt.descriptorType != typeNull)
  709.     {
  710.         err = AECopyParams(&fErrParams, &evt, false);
  711.         
  712.         if (err == noErr)
  713.         {
  714.             err = Exception::GetAEParams(evt, create);
  715.         }
  716.     }
  717.     
  718.     return err;
  719. }
  720.  
  721.  
  722. //------------------------------------------------------------------------------
  723.  
  724. bool StdException::GetErrorMessage(AEDesc& msg) const
  725. {
  726.     OSErr err;
  727.     bool  result = (fErrParams.descriptorType != typeNull);
  728.  
  729.     if (result)
  730.     {
  731.         err = AEGetKeyDesc(&fErrParams, keyErrorString, typeWildCard, &msg);
  732.  
  733.         if (!(result = (err == noErr)) && err != errAEDescNotFound)
  734.         {
  735.             GetLocationInCode().LogIfErr(err);
  736.         }
  737.     }
  738.  
  739.     return result;
  740. }
  741.  
  742. //------------------------------------------------------------------------------
  743.  
  744. bool StdException::PutErrorString(AERecord& event) const
  745. {
  746.     bool result = (fErrParams.descriptorType != typeNull);
  747.  
  748.     if (result)
  749.     {
  750.         AEDesc    temp;
  751.  
  752.         OSErr err =    AEGetKeyDesc(&fErrParams, keyErrorString, typeWildCard, &temp);
  753.  
  754.         if (err == noErr)
  755.         {
  756.             GetLocationInCode().LogIfErr(::AEPutParamDesc(&event, keyErrorString, &temp));
  757.         }
  758.         else
  759.         {
  760.             result = false;
  761.             GetLocationInCode().LogIfNotErr(err, errAEDescNotFound);
  762.         }
  763.         
  764.         AEDisposeDesc(&temp);
  765.     }
  766.  
  767.     return result;
  768. }
  769.  
  770. //------------------------------------------------------------------------------
  771.  
  772. bool StdException::CanAddErrorParam(AEKeyword param, bool overwrite)
  773. {
  774.     OSErr err = noErr;
  775.  
  776.     if (fErrParams.descriptorType == typeNull)
  777.     {
  778.         GetLocationInCode().LogIfErr(err = AECreateList(nil, 0, true, &fErrParams));
  779.     }
  780.     else if (!overwrite)
  781.     {
  782.         DescType    actualType;
  783.         Size        actualSize;
  784.  
  785.         err = AESizeOfKeyDesc(&fErrParams, param, &actualType, &actualSize);
  786.     }
  787.     
  788.     return (err == noErr || err == errAEDescNotFound);
  789. }
  790.  
  791. //------------------------------------------------------------------------------
  792.  
  793. bool StdException::HasErrorParam(AEKeyword    param) const
  794. {
  795.     OSErr        err = errAENoSuchObject;
  796.     DescType    actualType;
  797.     Size        actualSize;
  798.  
  799.     if (fErrParams.descriptorType != typeNull)
  800.     {
  801.         err = AESizeOfKeyDesc(&fErrParams, param, &actualType, &actualSize);
  802.     }
  803.  
  804.     return (err == noErr);
  805. }
  806.  
  807. //------------------------------------------------------------------------------
  808.  
  809. void StdException::PutErrorParamPtr(
  810.     AEKeyword    param,
  811.     DescType    type,
  812.     const void*    data,
  813.     Size        size,
  814.     bool        overwrite)
  815. {
  816.     if (CanAddErrorParam(param, overwrite))
  817.     {
  818.         GetLocationInCode().LogIfErr(AEPutKeyPtr(&fErrParams, param, type, data, size));
  819.     }
  820. }
  821.  
  822. //------------------------------------------------------------------------------
  823.  
  824. void StdException::PutErrorParamDesc(
  825.     AEKeyword        param,
  826.     const AEDesc&    desc,
  827.     bool            overwrite)
  828. {
  829.     if (CanAddErrorParam(param, overwrite))
  830.     {
  831.         GetLocationInCode().LogIfErr(AEPutKeyDesc(&fErrParams, param, &desc));
  832.     }
  833. }
  834.  
  835.  
  836. #if 0
  837.         NotifyFailureProc    gNotifyProc = nil;
  838.         
  839.         //--------------------------------------------------------------------------------
  840.         // Install a single routine called at failure time before
  841.         // exception processing begins.  This function is used in
  842.         // conjunction with ShowStackChain to record and later show
  843.         // the stack at the time of failure (left over from old 68K
  844.         // code that doesn't work too well on PowerPC).
  845.         void SetExceptionNotifyProc(NotifyFailureProc notifyProc)
  846.         {
  847.             gNotifyProc = notifyProc;
  848.         } // SetExceptionNotifyProc
  849.         
  850.         
  851.         //--------------------------------------------------------------------------------
  852.         // This routine is used by ReportError so that it knows whether or
  853.         // not it should show the 'sc6' button
  854.         Boolean ExceptionNotifyProcInstalled(void)
  855.         {
  856.             return gNotifyProc != nil;
  857.         } // ExceptionNotifyProcInstalled
  858.         
  859.         
  860.         //--------------------------------------------------------------------------------
  861.         // Notify that an error occured
  862.         void NotifyFailure(OSErr err)
  863.         {
  864.         #ifdef FAILMESSAGES
  865.             DebugPrintf("Failure caused by an error %d", err);
  866.         #endif
  867.         
  868.             // DebugStr("\pSomeone is about to fail...");
  869.         
  870.             if(gNotifyProc != nil)
  871.                 (*gNotifyProc)(err);
  872.         } // NotifyFailure
  873.         
  874.         
  875.         //--------------------------------------------------------------------------------
  876.         // This routine doesn't actually do anything; it's just used
  877.         // by the NOREGISTER macro
  878.         void MakeVariableNoRegister( void* foo )
  879.         {
  880.         
  881.         } // MakeVariableNoRegister
  882.         
  883. #endif
  884.  
  885.